package com.huika.lib.encrypt;

import java.security.NoSuchAlgorithmException;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * 接口中进行加密
 * 
 * @author
 *
 */
public class AESUtil {
	private static Cipher cipher;

	public static final String allChar = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

	public AESUtil() {

		try {
			cipher = Cipher.getInstance("AES/CBC/NoPadding");
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * AES加密
	 * 
	 * @param text
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public String encrypt(String text, String key) throws Exception {
		if (text == null || text.length() == 0)
			throw new Exception("Empty string");

		byte[] encrypted = null;

		IvParameterSpec ivspec = new IvParameterSpec(key.getBytes());

		SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");

		try {
			cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);

			encrypted = cipher
					.doFinal(padString(Base64.encode(text.getBytes()))
							.getBytes());
			// encrypted = cipher.doFinal(hexToBytes(text));

		} catch (Exception e) {
			throw new Exception("[encrypt] " + e.getMessage());
		}

		return AESUtil.bytesToHex(encrypted);
	}

	/**
	 * AES解密
	 * 
	 * @param code
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public String decrypt(String code, String key) throws Exception {
		if (code == null || code.length() == 0)
			throw new Exception("Empty string");

		byte[] decrypted = null;

		try {
			IvParameterSpec ivspec = new IvParameterSpec(key.getBytes());

			SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");

			cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

			decrypted = cipher.doFinal(hexToBytes(code));
		} catch (Exception e) {
			throw new Exception("[decrypt] " + e.getMessage());
		}
		try {
			String a = new String(decrypted, "UTF-8");
			System.out.println(a);
			String b = new String(Base64.decode(a), "UTF-8");
			return b;
		} catch (Exception e) {
			return new String(decrypted, "UTF-8");
		}

	}

	public static String bytesToHex(byte[] data) {
		if (data == null) {
			return null;
		}

		int len = data.length;
		String str = "";
		for (int i = 0; i < len; i++) {
			if ((data[i] & 0xFF) < 16)
				str = str + "0" + java.lang.Integer.toHexString(data[i] & 0xFF);
			else
				str = str + java.lang.Integer.toHexString(data[i] & 0xFF);
		}
		return str;
	}

	public static byte[] hexToBytes(String str) {
		if (str == null) {
			return null;
		} else if (str.length() < 2) {
			return null;
		} else {
			int len = str.length() / 2;
			byte[] buffer = new byte[len];
			for (int i = 0; i < len; i++) {
				buffer[i] = (byte) Integer.parseInt(
						str.substring(i * 2, i * 2 + 2), 16);
			}
			return buffer;
		}
	}

	private static String padString(String source) {
		char paddingChar = ' ';
		int size = 16;
		int x = source.length() % size;
		int padLength = size - x;

		for (int i = 0; i < padLength; i++) {
			source += paddingChar;
		}

		return source;
	}

	public static String initKey() throws Exception {
		AESUtil ase = new AESUtil();
		// 返回密钥的字符串
		return ase.generateString(16);
	}

	/**
	 * 返回一个定长的随机字符串(只包含大小写字母、数字)
	 * 
	 * @param length
	 *            随机字符串长度
	 * @return 随机字符串
	 */
	public static String generateString(int length) {
		StringBuffer sb = new StringBuffer();
		Random random = new Random();
		for (int i = 0; i < length; i++) {
			sb.append(allChar.charAt(random.nextInt(allChar.length())));
		}
		return sb.toString();
	}

	public static void main(String[] args) {
		AESUtil ase = new AESUtil();
		try {
			// String keyStr = ase.generateString(16);
			String keyStr = "kGMVwFUIgUorrIyp";
			System.out.println("秘钥：" + keyStr);

			// String sorceStr = Base64.encode("神奇的AES".getBytes());
			System.out.println("原字符串：" + "神奇的AES");
			// System.out.println("64位编码后的字符串：" + sorceStr);

			String encryptStr = ase.encrypt("神奇的AES", keyStr);

			System.out.println("加密后：" + encryptStr);

			String decryptStr = ase.decrypt(encryptStr, keyStr);

			System.out.println("解密后：" + decryptStr);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}
